#include <iostream>
#include <cstdint>
#include <functional>
#include <memory>
#include <vector>
#include <unistd.h>

// 使用环形缓冲区(60槽位)实现时间轮
// 通过智能指针管理任务生命周期
// 利用析构函数统一处理任务执行和清理
// 支持任务刷新和取消机制
// 特别适合非活跃连接超时处理场景


// 封装定时任务的唯一标识、超时时间、执行逻辑和取消状态
// 通过智能指针管理生命周期，析构时自动清理相关资源
using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;
class TimerTask // 定时任务的载体，封装任务逻辑和生命周期控制
{
public:
	TimerTask(uint64_t id, uint32_t timeout, const TaskFunc &task)
		: _id(id), _timeout(timeout), _task(task), _cancel(false)
	{
	}
	~TimerTask()
	{
		if (_cancel == false)
			_task(); // 取消定时任务销毁要在这任务模块完成，如果在时间轮完成还不是相当于销毁任务
		_releasetack(); // 把被weak_ptr管理起来的shared_ptr从_clone中移除，只有shared_ptr计数为0时才会进入析构函数
	}
	void SetReleaseTask(const ReleaseFunc &releasetack)
	{
		_releasetack = releasetack;
	}
	void Cancel() { _cancel = true; }
	int TimeOut() { return _timeout; }

private:
	uint64_t _id;			  // 定时任务id
	uint32_t _timeout;		  // 超时时间
	bool _cancel;			  // false表示不取消非活跃链接销毁，true表示取消
	TaskFunc _task;			  // 定时器对象要执行的定时任务
	ReleaseFunc _releasetack; // //用于删除TimerWheel中保存的定时器对象信息
};

// 维护一个环形时间轮结构，实现任务的定时调度
// 使用智能指针管理任务生命周期，避免循环引用
// 支持任务的添加、刷新、执行和取消操作
class TimerWheel // 时间轮管理器，负责任务的调度、执行和管理
{
private:
	void Remove(uint64_t id)
	{
		auto it = _clone.find(id);
		if (it != _clone.end())
		{
			// 找到了 进行移除
			_clone.erase(id);
		}
	}

public:
	TimerWheel()
		: _tick(0), _capacity(60), _wheel(_capacity)
	{
	}
	void TackAdd(uint64_t id, uint32_t timeout, const TaskFunc &task) // 添加定时任务
	{
		SharTask pt(new TimerTask(id, timeout, task));
		pt->SetReleaseTask(std::bind(&TimerWheel::Remove, this, id)); // 插入 释放保存的定时任务 函数，sherad_ptr管理的定时任务计数为0时，进行释放执行析构函数
		int ti = (_tick + timeout) % _capacity;
		_wheel[ti].push_back(pt);  // 把任务添加到时间轮去
		_clone[id] = WeakTask(pt); // 同时用weak_ptr把shared_ptr管理起来
	}
	void RefreshTack(uint64_t id) // 刷新定时任务
	{
		auto it = _clone.find(id);
		if (it == _clone.end())
		{
			// 没找到 直接返回
			return;
		}
		SharTask pt = it->second.lock(); // 找到保存的定时任务，对该任务进行生成一个shared_ptr,此时引用计数++
		if (!pt)
		{					  // lock() 失败处理
			_clone.erase(it); // 清理无效 weak_ptr
			return;
		}
		int del = pt->TimeOut(); // 获取超时时间
		int ti = (_tick + del) % _capacity;
		_wheel[ti].push_back(pt); // 将任务移动到新的时间点
	}
	void RunTimerTask() // 这个函数应该每秒钟被执行一次，相当于秒针向后走了一步
	{
		_tick = (_tick + 1) % _capacity;
		_wheel[_tick].clear(); // 清空指定位置的数组，就会把数组中保存的所有管理定时器对象的shared_ptr释放掉
	}
	void TaskChanel(uint64_t id) // 取消定时任务销毁
	{
		auto it = _clone.find(id);
		if (it == _clone.end())
		{
			// 没找到 直接返回
			return;
		}
		SharTask pt = it->second.lock();
		if (pt)
			pt->Cancel(); // lock成功进行取消
		_clone.erase(it); // 仅设置 _cancel 而不主动移除 _clone 记录，会导致 _clone 中残留无效数据
						  // 如果后续调用 RefreshTack(id)，会尝试刷新一个已取消的任务（虽然 _cancel = true，但逻辑上不应该再处理）
	}

private:
	using SharTask = std::shared_ptr<TimerTask>;
	using WeakTask = std::weak_ptr<TimerTask>;
	int _tick;									   // 每秒移动后的位置，执行该位置的定时任务
	int _capacity;								   // 时间轮的大小
	std::vector<std::vector<SharTask>> _wheel;	   // 时间轮，里面装的是用Sherad_ptr管理起来的定时任务
	std::unordered_map<uint64_t, WeakTask> _clone; // 保存每一个定时任务对象，但是用weak_ptr进行管理sherad_ptr对象，
												   // 防止循环引用，每个定时任务执行完毕后，要进行释放移除
};

class Task
{
public:
	Task()
	{
		std::cout << "构造" << std::endl;
	}
	~Task()
	{
		std::cout << "--------------------------------析构" << std::endl;
	}
};

void del(Task *t)
{
	delete t;
}

int main()
{
	TimerWheel wt;
	Task *t = new Task();
	wt.TackAdd(888, 5, std::bind(del, t));
	for (int i = 0; i < 5; i++)
	{
		sleep(1);
		wt.RefreshTack(888);
		wt.RunTimerTask();
		std::cout << "刷新定时任务，5秒后才会执行" << std::endl;
	}
	// wt.TaskChanel(888);
	while (1)
	{

		sleep(1);
		std::cout << "---------------" << std::endl;
		std::cout << "向后移动一位" << std::endl;
		wt.RunTimerTask();
	}
	return 0;
}